package com.example.util.poi;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class ExcelUtil {
    private static final   SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private ExcelUtil()
    {
    }

    public static <T> ExcelData downExcel2003(Class<T> tClass, List<T> dataList)
    {
        return new ExcelData(tClass,dataList,false);
    }

    public static <T> ExcelData downExcel2007(Class<T> tClass, List<T> dataList)
    {
        return new ExcelData(tClass,dataList,true);
    }

    public static class ExcelData<T>
    {
        private Workbook workbook;
        private String filaName = "excel";
        private ExcelData(Class<T> tClass, List<T> dataList,boolean is2007)
        {
            //首先获取属性集合以及对应属性，默认应该不用排序，按照属性声明顺序排序，如果不是，需要自己排序
            Field[] fields = tClass.getDeclaredFields();
            List<String> fieldNameList = new ArrayList<>();
            List<String> headNameList = new ArrayList<>();
            if (null!=fields&&fields.length>0)
            {
                for (Field field:fields)
                {
                    if (null!=field.getAnnotation(ExcelHead.class))
                    {
                        fieldNameList.add(field.getName());
                        headNameList.add(field.getAnnotation(ExcelHead.class).value());
                    }
                }
            }

            //list.get(0).getClass();这样也行，我TM ZZ了
            if (is2007)
            {
                workbook = new XSSFWorkbook();
                this.filaName = this.filaName+".xlsx";
            }else {
                workbook = new HSSFWorkbook();
                this.filaName = this.filaName+".xls";
            }

            //第二部，添加sheet和row第0行
            Sheet sheet = workbook.createSheet();
            Row row = sheet.createRow(0);

            //第三部，设置表头
            fillHeadRow(row, headNameList);
            //第四部，设置datalist
            fillDataList(sheet, dataList,fieldNameList);
        }

        private void fillDataList(Sheet sheet, List<T> dataList, List<String> fieldNameList) {
            int rows = dataList.size();
            int cloumns = fieldNameList.size();
            Row row;Cell cell;
            for (int i=0;i<rows;i++)
            {
                row = sheet.createRow(i+1);
                T t = dataList.get(i);
                for (int j=0;j<cloumns;j++)
                {
                    cell = row.createCell(j);
                    cell.setCellValue(getValueByFieldName(t,fieldNameList.get(j)));
                }
            }
        }

        private String getValueByFieldName(T t, String s) {
            Class<?> tClass = t.getClass();
            try {
                Field f = tClass.getDeclaredField(s);
                f.setAccessible(true);
                 Object o = f.get(t);
                 if (o instanceof Date)
                 {
                     return sdf.format(o);
                 }
                 return o.toString();
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            }
            catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            return null;
        }

        private void fillHeadRow(Row row, List<String> headNameList) {
            Cell cell;
            int len = headNameList.size();
            for (int i=0;i<len;i++)
            {
                cell = row.createCell(i);
                cell.setCellValue(headNameList.get(i));
                CellStyle style = workbook.createCellStyle();
                style.setWrapText(true);
                cell.setCellStyle(style);
            }
        }

        public ExcelData<T> fileName(String fileName){
            this.filaName = fileName;
            return this;
        }

        public void out(HttpServletResponse response){
            OutputStream out = null;
            try{
                response.setHeader("content-disposition", "attachment;filename="+this.filaName);
                //contenttype不用设置居然也可以
                out = response.getOutputStream();
                workbook.write(out);
            }catch (Exception e) {
                e.printStackTrace();
            }finally {
                if(out != null){
                    try {
                        out.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
